/*
Copyright [2012] [Maria Eugenia Malagamba]
Copyright [2012] [Leandro Pellegrino]
Copyright [2012] [Julia Gambuzzi]
Copyright [2012] [Ignacio Capodanno]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "Pintable.h"

using namespace Entidades;

Pintable::Pintable(double posicionX, double posicionY, string pathDeLaImagen, 
				   double anchoDeLaImagen, double altoDeLaImagen, double rotacionDeLaImagen)
{
	this->posicionX = posicionX;
	this->posicionY = posicionY;
	this->pathDeLaImagen = pathDeLaImagen;
	this->numeroFrame =0;
	this->maxFrames = 1;

	this->frames = new vector<SDL_Surface*>;

	//Carga la imagen y adecua el tamaño al que viene desde el xml
	SDL_Surface* imagenOriginal = this->cargarImagen(pathDeLaImagen);
	this->imagen = redimencionar(imagenOriginal,anchoDeLaImagen,altoDeLaImagen);
	this->frames->push_back(this->imagen);

	//La primera rotacion es igual a la imagen original
	this->ultimaRotacion = redimencionar(imagenOriginal,anchoDeLaImagen,altoDeLaImagen);

	//libero la imagen original y me quedo con la nueva redimencionada
	SDL_FreeSurface(imagenOriginal);

	this->anchoDeLaImagen = anchoDeLaImagen;
	this->altoDeLaImagen = altoDeLaImagen;
	this->setRotacionDeLaImagen( rotacionDeLaImagen);

};

Pintable::Pintable(string pathDeLaImagen, double anchoDeLaImagen, double altoDeLaImagen)
{
	this->posicionX = 0.0;
	this->posicionY = 0.0;
	this->pathDeLaImagen = pathDeLaImagen;
	this->numeroFrame =0;
	this->maxFrames = 1;

	this->frames = new vector<SDL_Surface*>;

	//Carga la imagen y adecua el tamaño al que viene desde el xml
	SDL_Surface* imagenOriginal = this->cargarImagen(pathDeLaImagen);
	this->imagen = redimencionar(imagenOriginal,anchoDeLaImagen,altoDeLaImagen);
	this->frames->push_back(this->imagen);

	//La primera rotacion es igual a la imagen original
	this->ultimaRotacion = redimencionar(imagenOriginal,anchoDeLaImagen,altoDeLaImagen);

	//libero la imagen original y me quedo con la nueva redimencionada
	SDL_FreeSurface(imagenOriginal);

	this->anchoDeLaImagen = anchoDeLaImagen;
	this->altoDeLaImagen = altoDeLaImagen;
	this->setRotacionDeLaImagen( 0.0);
};

Pintable::Pintable(double posicionX, double posicionY,string pathDeLaImagen, double anchoDeLaImagen, double altoDeLaImagen,double rotacionDeLaImagen, int cantidadFrames)
{
	this->posicionX = posicionX;
	this->posicionY = posicionY;
	this->pathDeLaImagen = pathDeLaImagen;
	this->numeroFrame =0;
	this->maxFrames = cantidadFrames;
	this->setRotacionDeLaImagen(rotacionDeLaImagen);

	this->anchoDeLaImagen = anchoDeLaImagen;
	this->altoDeLaImagen = altoDeLaImagen;

	//Carga la imagen y adecua el tamaño al que viene desde el xml
	SDL_Surface* imagenOriginal = this->cargarImagen(pathDeLaImagen);
	this->cargarFrames(imagenOriginal,true);

	this->imagen = this->frames->at(0);
	this->ultimaRotacion = this->cargarFrameX(imagenOriginal,0,true);

	SDL_FreeSurface(imagenOriginal);

	/*this->setRotacionDeLaImagen(0.0);*/
};


Pintable::Pintable(string pathDeLaImagen)
{
	this->rotacionDeLaImagen = 0;
	this->numeroFrame = 0;
	this->maxFrames = 6;

	SDL_Surface* imagenOriginal =  this->cargarImagen(pathDeLaImagen);
	this->cargarFrames(imagenOriginal);

	this->imagen = this->frames->at(0);
	this->ultimaRotacion = this->cargarFrameX(imagenOriginal,0);

	SDL_FreeSurface(imagenOriginal);
	//Posicion por defecto de la nave
	this->posicionX = 50;
	this->posicionY = 50;
	this->pathDeLaImagen = pathDeLaImagen;

	this->anchoDeLaImagen = this->imagen->w;
	this->altoDeLaImagen = this->imagen->h;;

};

Pintable::Pintable(){
	this->ultimaRotacion = NULL;
	this->frames = NULL;

};


void Pintable::cargarFrames(SDL_Surface* imagenOriginal){

	//Vector de frames del objeto
	this->frames = new vector<SDL_Surface*>;

	//voy agarrando uno a uno los frames del sprite y los guardo en el vector
	for (unsigned int i = 0; i < this->maxFrames; i++){

		SDL_Surface* frame =  this->cargarFrameX(imagenOriginal,i);

		this->frames->push_back(frame);
	}

}

SDL_Surface* Pintable::cargarFrameX(SDL_Surface* imagenOriginal, int numeroFrame){

	// creo una superficie vacia
	int altoFrame = imagenOriginal->h;
	int anchoFrame = imagenOriginal->w;
	SDL_Surface* frame = SDL_CreateRGBSurface(SDL_SWSURFACE, anchoFrame,altoFrame, 24,imagenOriginal->format->Rmask,imagenOriginal->format->Gmask, imagenOriginal->format->Bmask, 0);
	SDL_SetColorKey(frame, SDL_SRCCOLORKEY, SDL_MapRGB(frame->format,0,0,0));

	//Le pega el fuego a cualquier imagen
	SDL_Surface* fuego = this->cargarImagen("fire.bmp");
	SDL_Surface* fuegoRedimensionado = this->redimencionar(fuego, imagenOriginal->w * 0.50 * this->maxFrames,imagenOriginal->h);
	SDL_FreeSurface(fuego);

	//selecciono del sprite del fuego el frame
	SDL_Rect rect;
	int anchoFrameFuego = fuegoRedimensionado->w / this->maxFrames;
	rect.x = anchoFrameFuego * numeroFrame;
	rect.y = 0;
	rect.h = altoFrame;
	rect.w = anchoFrameFuego;

	// centro el fuego
	SDL_Rect centroDeLaImagen = {10,-8,0,0};

	//lleno la superficie con el frame correspondiente
	SDL_BlitSurface(fuegoRedimensionado,&rect,frame,&centroDeLaImagen);
	SDL_BlitSurface(imagenOriginal, NULL, frame,NULL);
	SDL_FreeSurface(fuegoRedimensionado);

	return  frame;
}

void Pintable::cargarFrames(SDL_Surface* imagenOriginal, bool sprite){

	//Vector de frames del objeto
	this->frames = new vector<SDL_Surface*>;

	//voy agarrando uno a uno los frames del sprite y los guardo en el vector
	for (unsigned int i = 0; i < this->maxFrames; i++){

		SDL_Surface* frame =  this->cargarFrameX(imagenOriginal,i,true);

		this->frames->push_back(frame);
	}

}

SDL_Surface* Pintable::cargarFrameX(SDL_Surface* imagenOriginal, int numeroFrame,bool sprite){

	// creo una superficie vacia del tamanio del sprite
	int altoFrame = imagenOriginal->h;
	int anchoFrame = imagenOriginal->w / this->maxFrames;

	SDL_Surface* frame = SDL_CreateRGBSurface(SDL_SWSURFACE, anchoFrame,altoFrame, 24,imagenOriginal->format->Rmask,imagenOriginal->format->Gmask, imagenOriginal->format->Bmask, 0);
	SDL_SetColorKey(frame, SDL_SRCCOLORKEY, SDL_MapRGB(frame->format,0,0,0));


	//selecciono del sprite del fuego el frame
	SDL_Rect rect;
	rect.x = anchoFrame * numeroFrame;
	rect.y = 0;
	rect.h = altoFrame;
	rect.w = anchoFrame;

	//lleno la superficie con el frame correspondiente
	SDL_BlitSurface(imagenOriginal,&rect,frame,NULL);
	SDL_Surface* frameRedimensionada = this->redimencionar(frame, this->anchoDeLaImagen,this->altoDeLaImagen);
	SDL_FreeSurface(frame);

	return  frameRedimensionada;
}

double Pintable::getPosicionX()
{
	return this->posicionX;
}

double Pintable::getPosicionY()
{ 
	return this->posicionY;
}

void Pintable::setPosicionY(double y){
	this->posicionY = y;
}

void Pintable::setPosicionX(double x){
	this->posicionX = x;

}

SDL_Surface* Pintable::cargarImagen(string path){

	SDL_Surface* imagen = SDL_LoadBMP(path.c_str());
	SDL_SetColorKey( imagen, SDL_SRCCOLORKEY, SDL_MapRGB(imagen->format, 128, 128, 128) );

	return imagen;
}

SDL_Surface * Pintable::getUltimaRotacion(){
	return this->ultimaRotacion;
}

void Pintable::setUltimaRotacion(SDL_Surface* ultimaRotacion){

	SDL_SetColorKey( ultimaRotacion, SDL_SRCCOLORKEY, SDL_MapRGB(ultimaRotacion->format,128,128,128) );
	this->ultimaRotacion = ultimaRotacion;
}

void Pintable::setImagen(SDL_Surface* imagen){

	SDL_SetColorKey( imagen, SDL_SRCCOLORKEY, SDL_MapRGB(imagen->format, 128, 128, 128) );
	this->imagen = imagen;
	this->frames->at(0)=this->imagen;

}


string Pintable::getPathDeLaImagen()
{
	return this->pathDeLaImagen; 
}

//El ancho real de la imagen es el de la ultimaRotacion
int Pintable::getAnchoDeLaImagen()
{
	return this->ultimaRotacion->w;
}

//El alto real de la imagen es el de la ultimaRotacion
int Pintable::getAltoDeLaImagen()
{ 
	return this->ultimaRotacion->h;
}


//Muestro el frame siguiente
void Pintable::siguienteFrame(){

	this->numeroFrame += 1;
	if (this->numeroFrame >= this->maxFrames)
		this->numeroFrame = this->maxFrames-2;

	this->imagen = this->frames->at(this->numeroFrame);

}

//Muestro el frame siguiente
void Pintable::framesCircular(){

	this->numeroFrame += 1;
	if (this->numeroFrame >= this->maxFrames)
		this->numeroFrame = 0;

	this->imagen = this->frames->at(this->numeroFrame);

}

//Muestro el frame anterior
void Pintable::frameAnterior(){
	this->numeroFrame -= 1;
	if (this->numeroFrame < 0)
		this->numeroFrame = 0;

	this->imagen = this->frames->at(this->numeroFrame);
}

double Pintable::getRotacionDeLaImagen()
{ 
	return this->rotacionDeLaImagen; 
}

void Pintable::setRotacionDeLaImagen(double rotacionDeLaImagen)
{ 
	if(rotacionDeLaImagen >= 360){
		rotacionDeLaImagen = rotacionDeLaImagen - 360;
	}
	if(rotacionDeLaImagen < 0){
		rotacionDeLaImagen = rotacionDeLaImagen + 360;
	}
	this->rotacionDeLaImagen = rotacionDeLaImagen; 
}

void Pintable::pintarImagen(SDL_Surface* superficiePantalla)
{
	SDL_Surface* imagenRotada = this->rotarImagen(superficiePantalla);

	SDL_FreeSurface(this->ultimaRotacion);
	this->setUltimaRotacion(imagenRotada);
}

SDL_Surface* Pintable::rotarImagen(SDL_Surface* ventana){

	int suavidad = 0;

	SDL_Surface* imagenOriginal = this->imagen;

	SDL_Surface* rotacionOptimizada = rotozoomSurface(imagenOriginal, this->rotacionDeLaImagen, 1, suavidad);

	//La dibujo en donde esta la imagen original.
	double x = this->getPosicionX();
	double y = this->getPosicionY();

	SDL_Rect posicionDeLaImagen = { x, y, 0, 0};
	SDL_SetColorKey(rotacionOptimizada, SDL_SRCCOLORKEY, SDL_MapRGB(rotacionOptimizada->format, 0,0,0) );
	SDL_BlitSurface(rotacionOptimizada,NULL, ventana, &posicionDeLaImagen);

	return rotacionOptimizada;
}

void Pintable::pintarImagen()
{
	SDL_Surface* imagenRotada = this->rotarImagen();

	SDL_FreeSurface(this->ultimaRotacion);
	this->setUltimaRotacion(imagenRotada);

}
SDL_Surface* Pintable::rotarImagen(){

	int suavidad = 0;

	SDL_Surface* imagenOriginal = this->imagen;

	SDL_Surface* rotacionOptimizada = rotozoomSurface(imagenOriginal, this->rotacionDeLaImagen, 1, suavidad);

	//La dibujo en donde esta la imagen original.
	double x = this->getPosicionX();
	double y = this->getPosicionY();

	//las posiciones se manejan en DOUBLE
	x -= (rotacionOptimizada->w - this->getAnchoDeLaImagen()) / 2;
	y -= (rotacionOptimizada->h - this->getAltoDeLaImagen()) / 2;

	this->setPosicionX(x);
	this->setPosicionY(y);

	return rotacionOptimizada;
}


//Cambia el tamaño de la imagen
SDL_Surface* Pintable::redimencionar(SDL_Surface* imagenOriginal,double ancho, double alto){

	//Calculo zoooX y zoomY
	double factorAncho = ancho/imagenOriginal->w;
	double factorAlto = alto/imagenOriginal->h;

	SDL_Surface* zoom = zoomSurface(imagenOriginal,factorAncho,factorAlto,SMOOTHING_OFF);
	SDL_SetColorKey( zoom, SDL_SRCCOLORKEY, SDL_MapRGB(zoom->format, 128,128,128) );

	return zoom;

}

void Pintable::setMaxNumeroDeFrame(int frames){
	this->maxFrames = frames;
}

int Pintable::getMaxNumeroDeFrame(){
	return this->maxFrames;
}

int Pintable::getNumeroDeFrame(){
	return this->numeroFrame;
}

void Pintable::setNumeroDeFrame(int numeroFrameActual){
	this->numeroFrame = numeroFrameActual;
	this->imagen = this->frames->at(this->numeroFrame);
}

double Pintable::getDireccionActual(){
	return this->direccionActual;
}

void Pintable::setDireccionActual(double direccionActual){
	this->direccionActual = direccionActual;
}

double Pintable:: getVelocidad(){
	return this->velocidad;
}

void Pintable::setVelocidad(double  velocidad){
	this->velocidad = velocidad;
}

Pintable::~Pintable(){

	if (this->ultimaRotacion != NULL)
		SDL_FreeSurface(this->ultimaRotacion);

	if ( this->frames != NULL){
		for(unsigned int i = 0; i < this->frames->size(); i++){
			SDL_FreeSurface(this->frames->at(i));
		}
		delete this->frames;
	}

}
